package com.cucn.ingmall.member.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cucn.common.utils.HttpUtils;
import com.cucn.common.utils.PageUtils;
import com.cucn.common.utils.Query;
import com.cucn.ingmall.member.dao.MemberDao;
import com.cucn.ingmall.member.entity.MemberEntity;
import com.cucn.ingmall.member.entity.MemberLevelEntity;
import com.cucn.ingmall.member.exception.PhoneExistExcetion;
import com.cucn.ingmall.member.exception.UserNameExistException;
import com.cucn.ingmall.member.service.MemberLevelService;
import com.cucn.ingmall.member.service.MemberService;
import com.cucn.ingmall.member.vo.GiteeUserDTO;
import com.cucn.ingmall.member.vo.MemberLoginVO;
import com.cucn.ingmall.member.vo.MemberRegistVO;
import com.cucn.ingmall.member.vo.SocialUser;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {
    @Resource
    private MemberLevelService memberLevelService;
    @Resource
    private MemberDao memberDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 用户注册功能
     *
     * @param registVO 注册基本信息
     */
    @Override
    public void regist(MemberRegistVO registVO) {
        MemberEntity member = new MemberEntity();

        //设置默认会员等级,新注册会员应该是默认等级1
        MemberLevelEntity memberLevel = memberLevelService.getDefaultMemberLevel();
        member.setLevelId(memberLevel.getId());

        //用户名和手机号要检查是否唯一
        checkPhoneUnique(registVO.getPhone());
        member.setMobile(registVO.getPhone());
        checkUserNameUnique(registVO.getUserName());
        member.setUsername(registVO.getUserName());

        //密码页面传过来是明文,数据库要进行加密存储
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = encoder.encode(registVO.getPassword());
        member.setPassword(password);

        //其他默认信息
        member.setNickname(registVO.getUserName());

        memberDao.insert(member);
    }

    @Override
    public void checkEmailUnique(String email) {
    }

    @Override
    public void checkUserNameUnique(String userName) throws UserNameExistException {
        Integer num = memberDao.selectUserNameIsUnique(userName);
        if (num > 0) {
            throw new UserNameExistException();
        }
    }

    @Override
    public void checkPhoneUnique(String phone) throws PhoneExistExcetion {
        Integer num = memberDao.selectPhoneIsUnique(phone);
        if (num > 0) {
            throw new PhoneExistExcetion();
        }
    }

    /**
     * 用户登录
     *
     * @param loginVO 登录vo
     * @return
     */
    @Override
    public MemberEntity login(MemberLoginVO loginVO) {
        String loginacct = loginVO.getLoginacct();
        String password = loginVO.getPassword();

        MemberEntity member = memberDao.selectMemberByAccount(loginacct);
        if (ObjectUtil.isEmpty(member)) {
            //查询为空,说明帐号不存在,返回null
            return null;
        } else {
            //帐号存在,继续比对密码,将原密码比编码后的密码进行匹配
            String passwordDb = member.getPassword();
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            boolean isPassword = passwordEncoder.matches(password, passwordDb);
            if (!isPassword) {
                return null;
            } else {
                return member;
            }
        }
    }

    /**
     * 社交登录(注册与登录二合一方法)
     *
     * @param socialUser 社交登录回调信息(带token)
     * @return
     */
    @Override
    public MemberEntity authLogin(SocialUser socialUser) throws Exception {
        Map<String, String> queryParam = new HashMap<>();
        queryParam.put("access_token", socialUser.getAccess_token());
        //携带token向码云发送请求,获取到具体用户信息
        HttpResponse response = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", new HashMap<>(), queryParam);

        if (response.getStatusLine().getStatusCode() == 200) {
            String s = EntityUtils.toString(response.getEntity());
            //获取社交用户所有社交信息
            GiteeUserDTO giteeUserDTO = JSON.parseObject(s, GiteeUserDTO.class);
            //获取gitee用户的id
            long giteeUserDTOId = giteeUserDTO.getId();

            //用户是否已经注册过?
            MemberEntity member = memberDao.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", giteeUserDTOId));
            if (ObjectUtil.isNotEmpty(member)) {
                //已注册,老用户登录,更新token
                MemberEntity updateMember = new MemberEntity();
                updateMember.setId(member.getId());
                updateMember.setAccessToken(socialUser.getAccess_token());
                updateMember.setExpiresIn(socialUser.getExpires_in());
                memberDao.updateById(updateMember);

                member.setAccessToken(socialUser.getAccess_token());
                member.setExpiresIn(socialUser.getExpires_in());
                return member;
            } else {
                //第一次登录,自动注册,set用户信息
                MemberEntity newMember = new MemberEntity();
                newMember.setSocialUid(String.valueOf(giteeUserDTOId));
                newMember.setAccessToken(socialUser.getAccess_token());
                newMember.setExpiresIn(socialUser.getExpires_in());

                newMember.setUsername(giteeUserDTO.getName());
                newMember.setNickname(giteeUserDTO.getName());
                newMember.setHeader(giteeUserDTO.getAvatar_url());

                MemberLevelEntity memberLevel = memberLevelService.getDefaultMemberLevel();
                newMember.setLevelId(memberLevel.getId());

                memberDao.insert(newMember);
                return newMember;
            }
        } else {
            return null;
        }
    }
}